#include"Mystdio.h"

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>

#define NOFLUSH 1
#define LINEFLUSH 2
#define ALLFLUSH 4
#define SUCCESS 99

_FILE* _fopen(const char* myfile, const char* mode)
{
    int fd = -1;
    if(strcmp(mode,"w") == 0)//写模式打开---"w"
    {
        fd = open(myfile,O_WRONLY|O_CREAT|O_TRUNC,0666);
    }
    else if(strcmp(mode,"a") == 0)//追加模式打开---"a"
    {
        fd = open(myfile,O_WRONLY|O_CREAT|O_APPEND,0666);
    }
    else if(strcmp(mode,"r") == 0)//只读模式打开---"r"
    {
        fd = open(myfile,O_RDWR);
    }
    
    _FILE* fp = (_FILE*)malloc(sizeof(_FILE));
    fp->fd = fd;
    fp->outbuffer[0] = '\0';
    fp->out_pos = 0;
    //fp->flushmode = LINEFLUSH;//采用行缓冲的默认策略
    fp->flushmode = ALLFLUSH;//采用全缓冲的策略
    return fp;
}


int _fwrite(const char* buffer, int size, int memb, _FILE* fp)
{
    if(fp->flushmode&LINEFLUSH){//采用行缓冲的方式
        memcpy(fp->outbuffer + (fp->out_pos), buffer,strlen(buffer));
        fp->out_pos = strlen(fp->outbuffer);//进到写函数后第一时间确定字符个数
        
        if(fp->outbuffer[fp->out_pos-1] == '\n'){//当最后一个字符是回车时，直接刷新缓冲区
            write(fp->fd, fp->outbuffer, size*memb);//先写入内核
            fp->outbuffer[0]='\0';//再清空缓存区
            fp->out_pos = 0;
            return SUCCESS;
        }
        else{//如果最后一个字符不是回车，缓冲区内容不刷新
           return SUCCESS;//同时out_pos的值不改变
        }
    }
    else if(fp->flushmode&ALLFLUSH){//采用全缓冲的方式(仅作为测试用)
        memcpy(fp->outbuffer + (fp->out_pos), buffer,strlen(buffer));
        fp->out_pos = strlen(fp->outbuffer);//进到写函数后第一时间确定字符个数
        
        if(fp->out_pos == SIZE){//当缓冲区已满，刷新缓冲区
            write(fp->fd, fp->outbuffer, size*memb);//先写入内核
            fp->outbuffer[0]='\0';//再清空缓存区
            fp->out_pos = 0;
            return SUCCESS;
        }
    }
    else{//采用无缓冲的方式(仅作为测试用)
        write(fp->fd,fp->outbuffer,size*memb);
        fp->outbuffer[0]='\0';//清空缓存区
        fp->out_pos = 0;
        return SUCCESS;
    }
    return fp->out_pos;
}

void _fclose(_FILE* fp)//_fclose要退出时将缓冲区的内容输出到文件里
{
    if(fp->out_pos){//当out_pos不为0，则说明缓冲区内仍有内容
        write(fp->fd,fp->outbuffer,strlen(fp->outbuffer));//将缓冲区字段传给内核
    }
    close(fp->fd);
}
